E) Template Meta Programming, TMP

템플릿을 이용해면 객체를 생성하지 않더라도, 타입에 어떠한 값을 부여할 수 있고,
해당 타입을 이용해서 연산을 할 수 있다.

타입은 반드신 컴파일 타임에 확정되어야 하므로, 컴파일 타임에 모든 연산이 끝나게 된다.
이와 같이 타입을 가지고 컴파일 타임에 생성되는 코드로 프로그래밍하는 것을
메타 프로그래밍(meta progrmming)이라고 한다.

C++에서는 템플릿을 이용해서 메타 프로그래밍을 할 수 있다.
#include <iostream>
template <int N>
struct Factorial{
static const int result=N*Factorial<N-1>::result;
};
template <>
struct Factorial<1>{
static const int result=1;
};
int main(void){
std::cout<<"6! = 1*2*3*4*5*6 = "<<Factorial<6>::result<<std::endl;
}

6! = 1*2*3*4*5*6 = 720

위 코드에서 실질적으로 값을 가지는 객체는 존재하지 않는다.
연산 결과인 720이라는 값은 컴파일러가 만들어낸 Factorial<6>이라는 타입을 나타내고 있을 뿐이다.

템플릿 메타 프로그램이으로 작성된 코드는 모두 컴파일 타임에 모든 연산이 종료된다.
따라서 프로그램 실행 소곧를 향상 시킬 수 있다.
(컴파일 시간은 많이 늘어나게 됨)

메타 프로그래밍은 구조가 매우 복잡하며, 작성된 코드에서 버그를 찾는 것이 매우 어렵다.
기본적으로 컴파일 타임에 연산을 하기 때문에 디버깅이 불가능하고, C++ 컴파일러는 특성상 템플릿 오류 시
긴 오류를 출력하게 된다.
최대공약수
일반 재귀 함수
int gcd(int a, int b){
if(b==0){
return a;
}
return gcd(b, a%b);
}
TMP
#include <iostream>
template <int X, int Y>
struct GCD{
static const int value=GCD<Y, X%Y>::value;
};
template <int X>
struct GCD<X, 0>{
static const int value=X;
};
int main(void){
std::cout<<"gcd(36, 24) :: "<<GCD<36, 24>::value<<std::endl;
return 0;
}

gcd(36, 24) :: 12

Ratio 클래스
#include <iostream>
#include <typeinfo>
template <int X, int Y>
struct GCD{
static const int value=GCD<Y, X%Y>::value;
};
template <int X>
struct GCD<X, 0>{
static const int value=X;
};
template <int N, int D=1>
struct Ratio{
typedef Ratio<N, D> type;
static const int num=N;
static const int den=D;
};
template <class R1, class R2>
struct _Ratio_add{
typedef Ratio<R1::num*R2::den+R2::num*R1::den, R1::den*R2::den> type;
};
template <class R1, class R2>
struct Ratio_add:_Ratio_add<R1, R2>::type{};
int main(void){
typedef Ratio<2, 3> rat;
typedef Ratio<3, 2> rat2;
typedef Ratio_add<rat, rat2> rat3;
std::cout<<rat3::num<<" / "<<rat3::den<<std::endl;
return 0;
}

13 / 6